package org.goldenport.g3.messages.datastore

import java.io._
import org.goldenport.util.{QSymbol, QSymbolSet}
import org.goldenport.g3.G3Command
import org.goldenport.g3.messages._
import org.goldenport.g3.messages.query.RecordQuery

/**
 * @since   Jun. 22, 2010
 * @version Jan.  4, 2011
 * @author  ASAMI, Tomoharu
 */
abstract class DataStoreCommand(uris: QSymbolSet) extends G3Command(uris.path) {
  def this(uri: QSymbol) = this(QSymbolSet(uri))
}

/**
 * Creates a kind.
 */
// XXX unify to CreateRecordClass
// XXX add Colleciton abstraction
class CreateKind(val kind: QSymbol) extends DataStoreCommand(kind) {
}

class CreateRecordClass(val recordClass: RecordClass) extends DataStoreCommand(recordClass.uri) {
  def schema = recordClass.schema
}

object Create {
  def apply(atom: Symbol, schema: RecordSchema) = new CreateRecordClass(RecordClass(atom, schema))

  def apply(recordClass: RecordClass) = new CreateRecordClass(recordClass)

  def apply(atom: Symbol) = new CreateKind(QSymbol(atom))
}

/**
 * Reads records by ids or condition.
 */
class FetchRecord(uri: QSymbol, val ids: List[Any]) extends DataStoreCommand(uri) {
}

class QueryRecord(val query: RecordQuery) extends DataStoreCommand(query.uris) {
}

class QueryRecordExample(uri: QSymbol, val record: Record) extends DataStoreCommand(uri) {
}

class QueryRecordExpression(uri: QSymbol, val expression: Expression) extends DataStoreCommand(uri) {
}

object Fetch {
  def apply(uri: QSymbol, id: Any) = new FetchRecord(uri, List(id))

  def apply(uri: QSymbol, ids: List[Any]) = new FetchRecord(uri, ids)
}

object Query {
  def apply(query: RecordQuery) = new QueryRecord(query)

  def apply(uri: QSymbol, example: Record) = new QueryRecordExample(uri, example)

  def apply(uri: QSymbol, expression: Expression) = new QueryRecordExpression(uri, expression)
}

/**
 * Inserts one record or some records.
 */
class InsertRecord(uri: QSymbol, val record: Record) extends DataStoreCommand(uri) {
}

class InsertRecordSet(uri: QSymbol, val records: RecordSet) extends DataStoreCommand(uri) {
}

object Insert {
  def apply(uri: QSymbol, record: Record) = new InsertRecord(uri, record)

  def apply(uri: QSymbol, records: RecordSet) = new InsertRecordSet(uri, records)

  def apply(uri: QSymbol, records: List[Record]) = new InsertRecordSet(uri, RecordSet(records))
}

/**
 * Updates one record or some records.
 */
class UpdateRecord(uri: QSymbol, val record: Record) extends DataStoreCommand(uri) {
}

class UpdateRecordSet(uri: QSymbol, val records: RecordSet) extends DataStoreCommand(uri) {
}

object Update {
  def apply(uri: QSymbol, record: Record) = new UpdateRecord(uri, record)

  def apply(uri: QSymbol, records: RecordSet) = new UpdateRecordSet(uri, records)

  def apply(uri: QSymbol, records: List[Record]) = new UpdateRecordSet(uri, RecordSet(records))
}

/**
 * Deletes records by ids or expression.
 */
class DeleteRecordId(uri: QSymbol, val ids: List[Any]) extends DataStoreCommand(uri) {
}

class DeleteRecordExample(uri: QSymbol, val record: Record) extends DataStoreCommand(uri) {
}

class DeleteRecordExpression(uri: QSymbol, val expression: Expression) extends DataStoreCommand(uri) {
}

object Delete {
  def apply(uri: QSymbol, id: Any) = new DeleteRecordId(uri, List(id))

  def apply(uri: QSymbol, ids: List[Any]) = new DeleteRecordId(uri, ids)

  def apply(uri: QSymbol, record: Record) = new DeleteRecordExample(uri, record)

  def apply(uri: QSymbol, expression: Expression) = new DeleteRecordExpression(uri, expression)
}

/**
 * Drops a kind.
 */
class DropKind(uri: QSymbol) extends DataStoreCommand(uri) {
}

object Drop {
  def apply(uri: QSymbol) = new DropKind(uri)
}

/**
 * Manifest
 */
class GetManifest() extends DataStoreCommand(QSymbol("/")) {
}
